/* 接口初探 */
// function printLabel(labelledObj: { label: string }) {
//     console.log(labelledObj.label);
// }
// let myObj = { size: 10, label: "Size 10 Object" };
// printLabel(myObj);

/*  */
// interface LabelledValue {
//     label: string;
// }
// function printLabel(labelledObj: LabelledValue) {
//     console.log(labelledObj.label);
// }
// let myObj = { size: 10, label: "Size 10 Object" };
// printLabel(myObj);

/* 可选属性 */
// interface SquareConfig {
//     color: string;
//     width?: number;
// }
// function createSquare(config: SquareConfig): { color: string; area: number } {
//     let newSquare = { color: "white", area: 100 };
//     if (config.color) {
//         newSquare.color = config.color;
//     }
//     if (config.width) {
//         newSquare.area = config.width * config.width;
//     }
//     return newSquare;
// }
// let mySquare = createSquare({ color: "black" });
// let mySquare2 = createSquare({ width: 1 });
// let mySquare3 = createSquare({  });
// console.log(mySquare);

/* 只读属性 */
// interface Point {
//     readonly x: number;
//     readonly y: number;
// }
// let p1: Point = { x: 10, y: 20 };
// p1.x = 5; // error!

/* 只读属性：ReadonlyArray */
// let a: number[] = [1, 2, 3, 4];
// let ro: ReadonlyArray<number> = a;
// ro[0] = 12; // error!
// ro.push(5); // error!
// ro.length = 100; // error!
// a = ro; // error!

/* 将只读数组断言为普通数组后即可执行写操作 */
// a = ro as number[];
// a[0] = 12;
// a.push(5);
// a.length = 100;

/* 函数类型 */
// interface SearchFunc {
//     (source: string, subString: string): boolean;
// }

// let mySearch: SearchFunc;
// mySearch = function(source: string, subString: string) {
//   let result = source.search(subString);
//   return result > -1;
// }

// /* 函数的参数名不需要与接口里定义的名字相匹配 */
// // let mySearch: SearchFunc;
// // mySearch = function(src: string, sub: string): boolean {
// //   let result = src.search(sub);
// //   return result > -1;
// // }
//
// /* 调用时自动进行参数类型推断 */
// let mySearch: SearchFunc;
// mySearch = function(src, sub) {
//     let result = src.search(sub);
//     return result > -1;
// }

/* 可索引的类型（选学） */
// interface StringArray {
//     [index: number]: string;
// }
// let myArray: StringArray;
// myArray = ["Bob", "Fred"];
// let myStr: string = myArray[0];
// console.log(myStr);

/* 可索引的类型: number类型的索引最终会先转化成string类型索引（选学） */
// class Animal {
//     name: string;
// }
// class Dog extends Animal {
//     breed: string;
// }

// // // 错误：使用'string'索引，有时会得到Animal!
// interface NotOkay {
//     [x: string]: Animal;
//     [x: number]: Dog;
// }
// let no:NotOkay;
// // no[0]=>no["0"]

/* 可索引的类型: 具体的value类型必须与索引声明的保持一致（选学） */
// interface NumberDictionary {
//     // 只要key是string 则必须值为number
//     [index: string]: number;
//     length: number; // 可以，length是number类型
//     // name: string; // 错误，`name`的类型与索引类型返回值的类型不匹配
// }
// let nd:NumberDictionary;
// nd[0]
// nd.length
// nd.name

/* 可索引的类型：将索引签名设置为只读（选学） */
// interface ReadonlyStringArray {
//     readonly [index: number]: string;
// }
// let myArray: ReadonlyStringArray = ["Alice", "Bob"];
// myArray[2] = "Mallory"; // error!

/* 类类型 */
/* 实现接口 */
// interface ClockInterface {
//     currentTime: Date;
// }

// // 实现接口
// class Clock implements ClockInterface {
//     currentTime: Date;
//     constructor(h: number, m: number) {}
// }

// interface ClockInterface {
//     currentTime: Date;
//     setTime(d: Date);
// }

// class Clock implements ClockInterface {
//     currentTime: Date;

//     // 对接口中定义的函数做具体实现
//     setTime(d: Date) {
//         this.currentTime = d;
//     }
//     constructor(h: number, m: number) { }
// }

/* 类静态部分与实例部分的区别 */
// interface ClockConstructor {
//     // 定义构造函数
//     new (hour: number, minute: number);
// }

// class Clock implements ClockConstructor {
//     currentTime: Date;
//     constructor(h: number, m: number) { }
// }

/* 构造函数与实例方法分开定义 */
// 定义实例部分
interface ClockInterface {
  tick();
}

// 定义构造函数
interface ClockConstructor {
  new (hour: number, minute: number): ClockInterface;
}

class DigitalClock implements ClockInterface {
  // 定义实例属性
  h: number;
  m: number;

  // 构造器
  constructor(h: number, m: number) {
    this.h = h;
    this.m = m;
  }

  // 定义示例方法
  tick() {
    setInterval(() => console.log("beep", this.h, this.m), 1000);
  }
}

// let digital = new DigitalClock(12, 17);
// digital.tick();

/* 在工厂方法中传入具体的构造器实现类 */
// function createClock(ctor: ClockConstructor,hour: number,minute: number): ClockInterface {
//   return new ctor(hour, minute);
// }
// let digital = createClock(DigitalClock, 12, 17);
// digital.tick();

/* 继承接口 */
// interface Shape {
//     color: string;
// }

// interface Square extends Shape {
//     // color: string;
//     sideLength: number;
// }

// let square = <Square>{};
// square.color = "blue";
// square.sideLength = 10;

interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends ShapeII, PenStroke {
    sideLength: number;
}

let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;

/* 混合类型（选学） */
// interface Counter {
//     (start: number): string;
//     interval: number;
//     reset(): void;
// }

// function getCounter(): Counter {
//     let counter = <Counter>function (start: number) { };
//     counter.interval = 123;
//     counter.reset = function () { };
//     return counter;
// }

// let c = getCounter();
// c(10);
// c.reset();
// c.interval = 5.0;

/* 接口继承类 */
class Control {
    state: any;
}

interface SelectableControl extends Control {
    select(): void;
}

class Button extends Control implements SelectableControl {
    select() {}
}
